/* eslint-disable */
import XLSX from 'xlsx'

function auto_width(ws, data) {
  /*set worksheet max width per col*/
  const colWidth = data.map(row =>
    row.map(val => {
      /*if null/undefined*/
      if (val == null) {
        return {
          wch: 10
        }
      } else if (val.toString().charCodeAt() > 255) {
        /*if chinese*/
        return {
          wch: val.toString().length * 2
        }
      } else {
        return {
          wch: val.toString().length
        }
      }
    })
  )
  /*start in the first row*/
  let result = colWidth[0]
  for (let i = 0; i < colWidth.length; i++) {
    for (let j = 0; j < colWidth[i].length; j++) {
      if (result[j]['wch'] < colWidth[i][j]['wch']) {
        result[j]['wch'] = colWidth[i][j]['wch']
      }
    }
  }
  ws['!cols'] = result
}

function json_to_array(key, jsonData) {
  return jsonData.map(v =>
    key.map(j => {
      return v[j]
    })
  )
}

// fix data,return string
function fixdata(data) {
  let o = ''
  let l = 0
  const w = 10240
  for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new UintArray(data.slice(l * w, l * w + w)))
  o += String.fromCharCode.apply(null, new UintArray(data.slice(l * w)))
  return o
}

// get head from excel file,return array
function get_header_row(sheet) {
  const headers = []
  const range = XLSX.utils.decode_range(sheet['!ref'])
  let C
  const R = range.s.r /* start in the first row */
  for (C = range.s.c; C <= range.e.c; ++C) {
    /* walk every column in the range */
    var cell =
      sheet[
        XLSX.utils.encode_cell({
          c: C,
          r: R
        })
      ] /* find the cell in the first row */
    var hdr = 'UNKNOWN ' + C // <-- replace with your desired default
    if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
    headers.push(hdr)
  }
  return headers
}

export const export_table_to_excel = (id, filename) => {
  const table = document.getElementById(id)
  const wb = XLSX.utils.table_to_book(table)
  XLSX.writeFile(wb, filename)

  /* the second way */
  // const table = document.getElementById(id);
  // const wb = XLSX.utils.book_new();
  // const ws = XLSX.utils.table_to_sheet(table);
  // XLSX.utils.book_append_sheet(wb, ws, filename);
  // XLSX.writeFile(wb, filename);
}

export const export_json_to_excel = ({ data, key, title, filename, autoWidth }) => {
  const wb = XLSX.utils.book_new()
  data.unshift(title)
  const ws = XLSX.utils.json_to_sheet(data, {
    header: key,
    skipHeader: true
  })
  if (autoWidth) {
    const arr = json_to_array(key, data)
    auto_width(ws, arr)
  }
  XLSX.utils.book_append_sheet(wb, ws, filename)
  XLSX.writeFile(wb, filename + '.xlsx')
}

// 导出不带有汉字标题的execel内容
export const export_array_to_excel = ({ key, data, title, filename, autoWidth }) => {
  const wb = XLSX.utils.book_new()
  const arr = json_to_array(key, data)
  arr.unshift(title)
  const ws = XLSX.utils.aoa_to_sheet(arr)
  if (autoWidth) {
    auto_width(ws, arr)
  }
  XLSX.utils.book_append_sheet(wb, ws, filename)
  XLSX.writeFile(wb, filename + '.xlsx')
}

/**
 * 通用的打开下载对话框方法，没有测试过具体兼容性
 * @param url 下载地址，也可以是一个blob对象，必选
 * @param saveName 保存文件名，可选
 */
function openDownloadDialog(url, saveName) {
  if (typeof url == 'object' && url instanceof Blob) {
    url = URL.createObjectURL(url) // 创建blob地址
  }
  var aLink = document.createElement('a')
  aLink.href = url
  aLink.download = saveName || '' // HTML5新增的属性，指定保存文件名，可以不要后缀，注意，file:///模式下不会生效
  var event
  if (window.MouseEvent) event = new MouseEvent('click')
  else {
    event = document.createEvent('MouseEvents')
    event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null)
  }
  aLink.dispatchEvent(event)
}

function sheet2blob(sheet, sheetName) {
  sheetName = sheetName || 'sheet1'
  var workbook = {
    SheetNames: [sheetName],
    Sheets: {}
  }
  workbook.Sheets[sheetName] = sheet
  // 生成excel的配置项
  var wopts = {
    bookType: 'xlsx', // 要生成的文件类型
    bookSST: false, // 是否生成Shared String Table，官方解释是，如果开启生成速度会下降，但在低版本IOS设备上有更好的兼容性
    type: 'binary'
  }
  var wbout = XLSX.write(workbook, wopts)
  var blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
  // 字符串转ArrayBuffer
  function s2ab(s) {
    var buf = new ArrayBuffer(s.length)
    var view = new Uint8Array(buf)
    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
    return buf
  }
  return blob
}

// 导出带有汉字标题的execel内容
export const export_array_to_excel_chinese = ({ key, data, title, filename, autoWidth }) => {
  const wb = XLSX.utils.book_new()
  const arr = json_to_array(key, data)
  arr.unshift(key)
  arr.unshift(title)
  arr.splice(1, 1)
  const ws = XLSX.utils.aoa_to_sheet(arr)
  if (autoWidth) {
    auto_width(ws, arr)
  }
  XLSX.utils.book_append_sheet(wb, ws, filename)
  XLSX.writeFile(wb, filename + '.xlsx')
}

export const export_test = () => {
  const data = [
    ['姓名', '年龄', '性别'],
    ['张三', 18, '男'],
    ['李四', 20, '女'],
    ['王五', 22, '男']
  ]
  const worksheet = XLSX.utils.aoa_to_sheet(data)
  const workbook = XLSX.utils.book_new()
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1')
  XLSX.writeFile(workbook, 'data.xlsx')
}

export const export_array_to_excel_merges = ({ data, filename, merges, cols }) => {
  var sheet = XLSX.utils.aoa_to_sheet(data)
  sheet['!merges'] = merges
  sheet['!cols'] = cols
  openDownloadDialog(sheet2blob(sheet), filename)
}

export const read = (data, type) => {
  const workbook = XLSX.read(data, {
    type: type
  })
  const firstSheetName = workbook.SheetNames[0]
  const worksheet = workbook.Sheets[firstSheetName]
  const header = get_header_row(worksheet)
  const results = XLSX.utils.sheet_to_json(worksheet)
  return {
    header,
    results
  }
}

export const readesxle = async (file, header, jsointitle) => {
  return new Promise(function(resolve, reject) {
    const resultdata = {
      ErrCode: '',
      ErrText: '导入文件格式不正确。',
      Rows: []
    }
    const fileExt = file.name
      .split('.')
      .pop()
      .toLocaleLowerCase()
    if (fileExt === 'xlsx' || fileExt === 'xls') {
      const reader = new FileReader()

      const thisXLSX = XLSX
      const thisheader = header
      const thisjsointitle = jsointitle
      reader.readAsArrayBuffer(file)
      reader.onloadstart = e => {}
      // reader.onprogress = e => {
      //   this.progressPercent = Math.round(e.loaded / e.total * )
      // }
      reader.onerror = e => {
        resultdata.ErrText = '文件读取出错'
        resultdata.ErrCode = ''
        resolve(resultdata)
      }
      reader.onload = e => {
        const data = e.target.result
        const workbook = thisXLSX.read(data, {
          type: 'array'
        })
        let tempFlag = true

        const firstSheetName = workbook.SheetNames[0]
        const worksheet = workbook.Sheets[firstSheetName]
        const sheetsheader = get_header_row(worksheet)
        const sheetarray = thisXLSX.utils.sheet_to_json(worksheet)

        thisheader.forEach((item, index) => {
          if (sheetsheader.findIndex(x => x == item) == -1) {
            tempFlag = false
          }
        })
        if (tempFlag) {
          let sheetresult = []
          for (let i = 0; i < sheetarray.length; i++) {
            sheetresult.push({})
            for (let j = 0; j < thisheader.length; j++) {
              if (sheetarray[i][thisheader[j]] == undefined || sheetarray[i][thisheader[j]] == null) sheetresult[i][thisjsointitle[j]] = ''
              else sheetresult[i][thisjsointitle[j]] = sheetarray[i][thisheader[j]]
            }
          }
          resultdata.ErrCode = ''
          resultdata.EErrText = '文件导入成功'
          resultdata.Rows = sheetresult
        } else {
          resultdata.ErrCode = ''
          resultdata.EErrText = '导入文件格式不正确。'
          resultdata.Rows = []
        }
        resolve(resultdata)
      }
    } else {
      resultdata.ErrCode = ''
      resultdata.ErrText = '文件：' + file.name + '不是EXCEL文件，请选择后缀为.xlsx或者.xls的EXCEL文件。'
      resolve(resultdata)
    }
  })
}

export const importExcel = callback => {
  var inputObj = document.createElement('input')
  inputObj.setAttribute('id', 'file')
  inputObj.setAttribute('type', 'file')
  inputObj.setAttribute('name', 'file')
  inputObj.setAttribute('style', 'visibility:hidden')
  inputObj.setAttribute('accept', '.xlsx,.xls,.csv')
  inputObj.addEventListener('change', evt => {
    const files = evt.target.files
    if (files && files[0])
      _file(files[0], (data, dataRef) => {
        callback(data, dataRef)
      })
  })
  document.body.appendChild(inputObj)
  inputObj.value
  inputObj.click()
}

function _file(file, callback) {
  const make_cols = refstr =>
    Array(XLSX.utils.decode_range(refstr).e.c + 1)
      .fill(0)
      .map((x, i) => ({
        name: XLSX.utils.encode_col(i),
        key: i
      }))

  /* Boilerplate to set up FileReader */
  const reader = new FileReader()
  reader.onload = e => {
    /* Parse data */
    const bstr = e.target.result
    const wb = XLSX.read(bstr, {
      type: 'binary'
    })
    /* Get first worksheet */
    const wsname = wb.SheetNames[0]
    const ws = wb.Sheets[wsname]
    /* Convert array of arrays */
    const data = XLSX.utils.sheet_to_json(ws, {
      header: 1
    })
    /* Update state */
    callback(data, make_cols(ws['!ref']))
  }
  reader.readAsBinaryString(file)
}

export default {
  export_table_to_excel,
  export_array_to_excel,
  export_json_to_excel,
  export_array_to_excel_chinese,
  export_array_to_excel_merges,
  read,
  export_test,
  importExcel,
  readesxle
}
